#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <string.h>

#include "help_api.h"
#include "fake_int.h"

int fd = 0;
void *map = 0;
char temp_filename[15] = "";

int open_temp_file(){
	int sfp;
	int fd = -1;
	 
	strncpy(temp_filename, "/tmp/fi.XXXXXX", sizeof (temp_filename));
	if ((fd = mkstemp(temp_filename)) == -1 ||
		(sfp = open(temp_filename, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600))==0 ) {
		  if (fd != -1) {
		    unlink(temp_filename);
		    close(fd);
		  }
	   debug_print("fake_int.cpp: %s\n", temp_filename);
	   return -1;
	}
	return (sfp);
}

void prep_fake_int(){
	if(fd && map)
		return;

	int i;

    int result;
    
	//temp_filename = tempnam("/tmp",temp_template);
	

    /* Open a file for writing.
     *  - Creating the file if it doesn't exist.
     *  - Truncating it to 0 size if it already exists. (not really needed)
     *
     * Note: "O_WRONLY" mode is not sufficient when mmaping.
     */
    //fd = open(temp_template, O_RDWR | O_CREAT | O_TRUNC, (mode_t)0600);
	fd = (int)open_temp_file();   
	if (fd == -1) {
		debug_print("fake_int.cpp: Error opening file for writing\n");
		throw 0;
    }

    /* Stretch the file size to the size of the (mmapped) array of ints
     */
    result = lseek(fd, FILESIZE-1, SEEK_SET);
    if (result == -1) {
		close(fd);
		debug_print("fake_int.cpp: Error calling lseek() to 'stretch' the file\n");
		throw 0;
    }
    
    /* Something needs to be written at the end of the file to
     * have the file actually have the new size.
     * Just writing an empty string at the current file position will do.
     *
     * Note:
     *  - The current position in the file is at the end of the stretched 
     *    file due to the call to lseek().
     *  - An empty string is actually a single '\0' character, so a zero-byte
     *    will be written at the last byte of the file.
     */
    result = write(fd, "", 1);
    if (result != 1) {
		close(fd);
		debug_print("fake_int.cpp: Error writing last byte of the file\n");
		throw 0;
    }

    /* Now the file is ready to be mmapped.
     */
    map = mmap((void*)FAKE_INT_ADDR, FILESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (map == MAP_FAILED) {
		close(fd);
		debug_print("fake_int.cpp: Error mmapping the file\n");
		throw 0;
    }
    debug_print("fake_int.cpp: mmap address : %08X\n", (int)map);
}

void release_fake_int(){
    /* Don't forget to free the mmapped memory
     */
    if (munmap(map, FILESIZE) == -1) {
		debug_print("fake_int.cpp: Error un-mmapping the file");
		throw 0;
    }

    /* Un-mmaping doesn't close the file, so we still need to do that.
     */
    close(fd);
	unlink(temp_filename);
}

handler_func getvect(int intr_num)
{
	return (handler_func)(*((int*)(FAKE_INT_ADDR + intr_num)));
} 

void setvect(int intr_num, handler_func handler)
{
	*((int*)(FAKE_INT_ADDR + intr_num)) = (int)handler;
} 

/*
int main(int argc, char *argv[])
{
   
	prep_fake_int();
	setvect(0xC, 0x1337dead);
	printf("0xc int : %08X\n", getvect(0xC));

	release_fake_int();
	debug_print("fake_int.cpp: all gut!!!\n");
    return 0;
}*/
